<template>
  <div class="p-8 max-w-3xl mx-auto">
    <h1 class="text-2xl font-semibold">UUID 生成器（UUID Generator）</h1>
    <p class="mt-2 text-gray-600">生成标准 UUID（支持 v4 随机以及 v5 名称空间生成）。</p>

    <div class="mt-6 mb-6">
      <label class="block text-sm font-medium text-gray-700 mb-2">生成的 UUID</label>
      <div class="flex items-center gap-2">
        <input v-model="output" readonly class="flex-1 px-3 py-2 border rounded bg-gray-50" />
        <button @click="copy" class="px-3 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">复制</button>
        <button @click="generate" class="px-3 py-2 border rounded hover:bg-gray-100">生成</button>
        <button @click="downloadAll" class="px-3 py-2 border rounded hover:bg-gray-100">下载</button>
      </div>
      <p v-if="copySuccess" class="text-sm text-green-600 mt-2">已复制到剪贴板</p>
      <p v-if="error" class="text-sm text-red-600 mt-2">{{ error }}</p>
    </div>

    <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
      <div>
        <label class="block text-sm text-gray-700 mb-1">版本</label>
        <select v-model="version" class="w-full px-3 py-2 border rounded bg-white">
          <option value="v4">v4（随机）</option>
          <option value="v5">v5（名称空间 / SHA-1）</option>
        </select>
      </div>

      <div>
        <label class="block text-sm text-gray-700 mb-1">生成数量</label>
        <input type="number" v-model.number="count" min="1" max="1000" class="w-24 px-2 py-1 border rounded" />
      </div>
    </div>

    <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
      <label class="inline-flex items-center"><input type="checkbox" v-model="upperCase" class="mr-2"> 大写</label>
      <label class="inline-flex items-center"><input type="checkbox" v-model="noHyphens" class="mr-2"> 去除连字符</label>
    </div>

    <div v-if="version === 'v5'" class="mb-6">
      <label class="block text-sm text-gray-700 mb-1">名称 (name)</label>
      <input v-model="name" class="w-full px-3 py-2 border rounded" placeholder="用于 v5 的名字，例如：example.com" />

      <label class="block text-sm text-gray-700 mt-3 mb-1">命名空间 UUID (namespace)</label>
      <input v-model="namespace" class="w-full px-3 py-2 border rounded" placeholder="例如：6ba7b810-9dad-11d1-80b4-00c04fd430c8 (DNS)" />
      <p class="text-sm text-gray-500 mt-2">v5 需要名称与命名空间（RFC4122），常用命名空间：DNS: 6ba7b810-9dad-11d1-80b4-00c04fd430c8，URL: 6ba7b811-9dad-11d1-80b4-00c04fd430c8</p>
    </div>

    <div class="flex items-center gap-3">
      <NuxtLink to="/generator-tools" class="text-blue-600 hover:underline">返回生成工具列表</NuxtLink>
      <button @click="generate" class="ml-auto px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700">生成 UUID</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useTools } from '~/composables/useTools'

useHead({ title: 'UUID 生成器 - 八八在线工具' })

const { copyToClipboard, downloadFile } = useTools()

const output = ref('')
const version = ref('v4')
const count = ref(1)
const upperCase = ref(false)
const noHyphens = ref(false)
const name = ref('')
const namespace = ref('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
const copySuccess = ref(false)
const error = ref('')

function bytesToUuid(buf, offset = 0) {
  const b = []
  for (let i = 0; i < 16; i++) b.push((buf[offset + i] || 0).toString(16).padStart(2, '0'))
  const uuid = `${b.slice(0,4).join('')}-${b.slice(4,6).join('')}-${b.slice(6,8).join('')}-${b.slice(8,10).join('')}-${b.slice(10,16).join('')}`
  return uuid
}

function uuidToBytes(uuid) {
  const s = uuid.replace(/[^0-9a-f]/gi, '')
  if (s.length !== 32) throw new Error('Invalid UUID')
  const out = new Uint8Array(16)
  for (let i = 0; i < 16; i++) out[i] = parseInt(s.substr(i*2,2), 16)
  return out
}

function generateV4() {
  const rnds = new Uint8Array(16)
  if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
    crypto.getRandomValues(rnds)
  } else {
    for (let i = 0; i < 16; i++) rnds[i] = Math.floor(Math.random() * 256)
  }
  // Per RFC4122 set bits
  rnds[6] = (rnds[6] & 0x0f) | 0x40 // version 4
  rnds[8] = (rnds[8] & 0x3f) | 0x80 // variant
  return bytesToUuid(rnds)
}

async function generateV5(nameStr, namespaceUuid) {
  if (!nameStr) throw new Error('v5 需要名称 (name)')
  let nsBytes
  try {
    nsBytes = uuidToBytes(namespaceUuid)
  } catch (e) {
    throw new Error('无效的命名空间 UUID')
  }
  const enc = new TextEncoder()
  const nameBytes = enc.encode(nameStr)
  const toHash = new Uint8Array(nsBytes.length + nameBytes.length)
  toHash.set(nsBytes, 0)
  toHash.set(nameBytes, nsBytes.length)
  const hashBuffer = await crypto.subtle.digest('SHA-1', toHash)
  const hash = new Uint8Array(hashBuffer).slice(0,16)
  hash[6] = (hash[6] & 0x0f) | 0x50 // version 5
  hash[8] = (hash[8] & 0x3f) | 0x80 // variant
  return bytesToUuid(hash)
}

async function generate() {
  error.value = ''
  copySuccess.value = false
  const n = Number(count.value) || 1
  if (n < 1 || n > 1000) {
    error.value = '数量应在 1 到 1000 之间'
    return
  }
  try {
    const arr = []
    for (let i = 0; i < n; i++) {
      let u
      if (version.value === 'v4') {
        u = generateV4()
      } else if (version.value === 'v5') {
        u = await generateV5(name.value || '', namespace.value || '')
      }
      if (noHyphens.value) u = u.replace(/-/g, '')
      if (upperCase.value) u = u.toUpperCase()
      arr.push(u)
    }
    output.value = arr.join(n === 1 ? '' : '\n')
  } catch (e) {
    error.value = e.message || String(e)
  }
}

async function copy() {
  if (!output.value) return
  const ok = await copyToClipboard(output.value)
  if (ok) {
    copySuccess.value = true
    setTimeout(() => (copySuccess.value = false), 2000)
  } else {
    error.value = '复制失败（浏览器不支持）'
  }
}

function downloadAll() {
  if (!output.value) return
  const filename = `uuids_${new Date().toISOString().replace(/[:.]/g,'-')}.txt`
  downloadFile(output.value, filename, 'text/plain')
}

// auto-generate one on load
generate()
</script>
